package com.infore.qualityControl.util;

import java.math.BigDecimal;
import java.util.List;

/**
 * 最小二乘法拟合 y=ax+b 
 * @author xiaolei
 *
 */
public class TheleastsquaremethodUtils {
	
	/**
	 * 拟合直线方程-获取斜率
	 *  公式：a=(NΣxy-ΣxΣy)/(NΣx²-(Σx)²)
	 * @param x
	 * @param y
	 * @return 斜率
	 */
	public static double slope(List<Double> x, List<Double> y) {
		double sumXY = 0.0, sumX = 0.0, sumY = 0.0, sumXSquare = 0.0;
		int index = x.size() < y.size() ? x.size() : y.size();
		for (int i = 0; i < index; i++) {
			sumXY += x.get(i) * y.get(i);
			sumX += x.get(i);
			sumY += y.get(i);
			sumXSquare += Math.pow(x.get(i), 2.0);
		}
		return (index * sumXY - sumX * sumY) / (index * sumXSquare - Math.pow(sumX, 2.0));
	}

	/**
	 * 拟合直线方程-获取截距 
	 * 公式：b=yAverage-a*xAverage
	 * @param x
	 * @param y
	 * @return 截距
	 */
	public static double intercept(List<Double> x, List<Double> y) {
		double sumX = 0.0, sumY = 0.0;
		int index = x.size() < y.size() ? x.size() : y.size();
		for (int i = 0; i < index; i++) {
			sumX += x.get(i);
			sumY += y.get(i);
		}
		return sumY / index - slope(x, y) * sumX / index;
	}
	
	
	/**
	 * 拟合直线方程-获取相关系数r
	 * 公式:r=(Σ(x-xAverage)(y-yAverage))/√Σ(x-xAverage)²Σ(y-yAverage)²
	 * @param x
	 * @param y
	 * @return 相关系数
	 */
	public static double correlationCoefficient(List<Double> x, List<Double> y) {
		double XAverage = 0.0, YAverage = 0.0, sumX = 0.0, sumY = 0.0;
		double sumXReduceXAverage = 0.0, sumYReduceYAverage = 0.0, sumSquareXReduceXAverage = 0.0, sumSquareYReduceYAverage = 0.0, sum = 0.0;
		int index = x.size() < y.size() ? x.size() : y.size();
		for (int i = 0; i < index; i++) {
			sumX += x.get(i);
			sumY += y.get(i);
			XAverage = sumX/index;
			YAverage = sumY/index;
		}
		for (int i = 0; i < index; i++) {
			sumXReduceXAverage = x.get(i) - XAverage;
			sumYReduceYAverage = y.get(i) - YAverage;
			sum += sumXReduceXAverage * sumYReduceYAverage;
			sumSquareXReduceXAverage += Math.pow(x.get(i) - XAverage, 2.0);
			sumSquareYReduceYAverage += Math.pow(y.get(i) - YAverage, 2.0);
		}
		double r = sum / Math.sqrt(sumSquareXReduceXAverage * sumSquareYReduceYAverage);
		BigDecimal bigDecimal = new BigDecimal(r);
		double result = bigDecimal.setScale(4, BigDecimal.ROUND_HALF_UP).doubleValue();
		return result;
	}

//    //测试	
//	public static void main(String[] args) {
//		double[] a = { 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9  } ;  
//        double[] b = {23 , 44 , 32 , 56 , 33 , 34 , 55 , 65 , 45 , 55} ; 
//        List<Double> x = new ArrayList<Double>();
//        List<Double> y = new ArrayList<Double>();
//        
//        for(int i = 0; i < a.length; i++) {
//        	x.add(a[i]);
//        	y.add(b[i]);
//        }
//        
//        System.out.println("斜率：" + TheleastsquaremethodUtils.slope(x, y));
//        System.out.println("截距：" + TheleastsquaremethodUtils.intercept(x, y));
//        System.out.println("相关系数：" + TheleastsquaremethodUtils.correlationCoefficient(x, y));
//	}

}
